package com.qunar.wan.web.controller;

import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.qunar.wan.common_api.model.AdminLog;
import com.qunar.wan.common_api.model.User;
import com.qunar.wan.common_api.model.enums.Role;
import com.qunar.wan.common_api.service.AdminLogService;
import com.qunar.wan.common_api.service.UserService;
import com.qunar.wan.web.filter.AuthenticationController;
import org.apache.commons.lang3.StringUtils;
import com.qunar.wan.common_api.serializer.RowBounds;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * User: hangyu.shen Date: 13-11-28 Time: 下午1:56
 * <p/>
 * 超级管理员增删管理员、查看管理员日志
 */
@Controller
@RequestMapping("admin/adminLog")
public class AdminLogController implements AuthenticationController {
    @Resource
    private AdminLogService adminLogService;
    @Resource
    private UserService userService;

    // 后台页面每页显示的记录数
    private int pageSize = 15;
    // 初始页码
    private final int ORIGIN_PAGE = 1;
    // 根据管理员id查找到日志信息并分页
    private final int PAGING_BY_ID = 0;
    // 根据管理员操作时间查找到日志信息并分页
    private final int PAGING_BY_DATE = 1;
    // 如果是第一次通过id查询管理员日志则记录管理员该条日志信息，否则不记录
    private boolean isFirstQueryLogById = true;
    // 如果是第一次通过日期查询管理员日志则记录管理员该条日志信息，否则不记录
    private boolean isFirstQueryLogByDate = true;

    /**
     * 超级管理员登陆成功后显示所有管理员用户名页
     * 
     * @param msg 供jsp页面显示的信息
     * @return 跳转显示所有管理员信息显示页
     */
    @RequestMapping("/showAllAdminInfo")
    public ModelAndView showAllAdminInfo(String msg) {
        Map<String, Object> map = Maps.newHashMap();
        List<User> listAdmin = userService.selectUserByRole(Role.MANAGER);
        map.put("msg", msg);
        map.put("listAdmin", listAdmin);
        return new ModelAndView("activity/showAllAdminInfo", "listAdmin", map);
    }

    /**
     * 供超级管理员添加管理员
     * 
     * @param map 返回给jsp页面的信息
     * @param pageCurId jsp分页的当前页码
     * @return 跳转显示所有用户信息显示页，供超级管理员增加管理员
     */
    @RequestMapping("/showAllUserInfo")
    public String showAllUserInfo(ModelMap map,
            @RequestParam(value = "pageCurId", required = false, defaultValue = "1") int pageCurId) {
        int offset = (pageCurId - 1) * pageSize;
        int total = userService.selectUserNum();
        List<User> listUser = userService.selectAllUser(new RowBounds(offset, pageSize));
        // flag标记用于判断是否显示显示上一页下一页进行分页，1--显示分页，0--不分页
        map.put("flag", true);
        map.put("pageCurId", pageCurId);
        map.put("total", (int) Math.ceil((double) total / pageSize));
        map.put("listUser", listUser);
        return "activity/showAllUser";
    }

    /**
     * 根据请求分页显示对应管理员的日志信息
     * 
     * @param adminId 管理员id
     * @param pageCurId jsp分页的当前页码
     * @return 跳转到某个管理员的日志显示页
     */
    @RequestMapping("/showAdminLog")
    public ModelAndView getAdminLogById(HttpServletRequest request,
            @RequestParam(value = "adminId", required = false, defaultValue = "0") int adminId,
            @RequestParam(value = "pageCurId", required = false, defaultValue = "1") int pageCurId) {
        // 分页
        Map<String, Object> map = paging(pageCurId, adminId, null, PAGING_BY_ID);
        // 获取cookie信息并插入日志
        if (isFirstQueryLogById == true) {
            isFirstQueryLogById = false;
            User user = Preconditions.checkNotNull(userService.currentLogonUser());
            String str = String.format("查看管理员'%s'的日志信息", user.getUserName());
            adminLogService.insertAdminLog(user.getId(), str);
        }

        return new ModelAndView("activity/listAdminLog", "mapAdminLog", map);
    }

    /**
     * 根据用户名查找并设置管理员
     * 
     * @param userName 用户名
     * @param map 返回给jsp页面的信息
     * @return 跳转显示根据用户名查询到的管理员信息页面
     */
    @RequestMapping("/showUser")
    public String getUserByName(@RequestParam(value = "userName") String userName, ModelMap map,
            HttpServletRequest request) {
        User user = userService.selectUserByName(userName);
        // 将user对象数据转为List列表，方便重用showAllUser.jsp界面
        List<User> listUser = Lists.newArrayList();
        listUser.add(user);
        if (null == user) {
            map.put("msg", "您输入的用户名不存在，请重新输入");
        }
        // flag标记用于判断是否显示显示上一页下一页进行分页，1--显示分页，0--不分页(通过用户名查询只有一条记录或无记录，不需分页)
        map.put("flag", false);
        map.put("listUser", listUser);
        // 获取cookie信息并插入日志
        int adminId = Preconditions.checkNotNull(userService.currentLogonUser()).getId();
        String str = String.format("搜索管理员'%s'", userName);
        adminLogService.insertAdminLog(adminId, str);

        return "activity/showAllUser";
    }

    /**
     * 删除或添加管理员
     * 
     * @param adminId 管理员id
     * @param flag 判断是删除还是增加管理员,0--删除，1--增加
     * @return 跳转showAllAdminInfo方法返回的跳转页
     */
    @RequestMapping("/deleteOrAddAdmin")
    public Object deleteOrAddAdminByUserId(HttpServletRequest request, @RequestParam(value = "adminId") int adminId,
            @RequestParam(value = "flagValue") int flag) {
        // 获取cookie信息并插入日志（事务）
        int supAdminId = (userService.currentLogonUser()).getId();
        // 增删管理员并插入日志信息
        String msg = adminLogService.deleteOrAddAdminTran(supAdminId, adminId, flag);

        return showAllAdminInfo(msg);
    }

    /**
     * 通过查询日期来查找对应管理员的日志（某天及该天之后的所有日志信息）
     * 
     * @param actionDate 输入的日期
     * @param pageCurId 分页的当前页
     * @param userId 管理员id
     * @return 跳转根据日期查询到的管理员日志信息页
     */
    @RequestMapping("/getAdminLogByActionDate")
    public ModelAndView getAdminLogByActionDate(@RequestParam(value = "actionDate") String actionDate,
            @RequestParam(value = "pageCurId", required = false, defaultValue = "1") int pageCurId,
            @RequestParam(value = "userId") int userId, HttpServletRequest request) {
        // 分页
        Map<String, Object> map = paging(pageCurId, userId, actionDate, PAGING_BY_DATE);
        // 获取cookie信息并插入日志
        if (isFirstQueryLogByDate == true) {
            isFirstQueryLogByDate = false;
            int adminId = Preconditions.checkNotNull(userService.currentLogonUser()).getId();
            User user = userService.selectUserById(userId);
            String str = String.format("通过日期查询管理员'%s'的日志信息", user.getUserName());
            adminLogService.insertAdminLog(adminId, str);
        }

        return new ModelAndView("activity/listAdminLog", "mapAdminLog", map);
    }

    /**
     * 供超级管理员查看个人日志信息
     * 
     * @param request
     * @return
     */
    @RequestMapping("/personalLog")
    public ModelAndView getPersonalLog(HttpServletRequest request) {
        int adminId = Preconditions.checkNotNull(userService.currentLogonUser()).getId();
        adminLogService.insertAdminLog(adminId, "查看个人日志信息");
        // 1--表示初始页码
        return getAdminLogById(request, adminId, ORIGIN_PAGE);
    }

    /**
     * 分页方法
     * 
     * @param pageCurId 当前页码
     * @param userId 用户id
     * @param actionDate 记录日志日期
     * @param flag 标记：0--根据用户id查找日志并分页；1--根据日志记录时间查找日志并分页
     * @return 返回map
     */
    private Map<String, Object> paging(int pageCurId, int userId, String actionDate, int flag) {
        // 获取需分页的总页数
        int total;
        // 存放一页数据
        List<AdminLog> listAdminLog;
        int offset = pageSize * (pageCurId - 1);
        Map<String, Object> map = Maps.newHashMap();

        if (0 == flag) {
            // flag为0：通过管理员id查找到日志信息的分页显示
            total = adminLogService.getAdminLogCountByUserId(userId, "");
            listAdminLog = adminLogService.selectListByUserId(userId, new RowBounds(offset, pageSize));
        } else if (1 == flag) {
            // flag为1：通过日期查找到的管理员日志信息的分页显示
            total = adminLogService.getAdminLogCountByUserId(userId, actionDate);
            listAdminLog = adminLogService.selectListByDate(actionDate, userId, new RowBounds(offset, pageSize));
        } else {
            return Collections.EMPTY_MAP;
        }
        map.put("flag", flag);
        map.put("actionDate", actionDate);
        map.put("total", (int) Math.ceil((double) total / pageSize));
        map.put("pageCurId", pageCurId);
        map.put("adminId", userId);
        map.put("listAdminLog", listAdminLog);

        return map;
    }

    private Function<User, Integer> userToIdFunction = new Function<User, Integer>() {
        @Override
        public Integer apply(User user) {
            return user.getId();
        }
    };

    @Override
    public boolean isAuthenticated(String pathInfo, ServletRequest req) {
        List<User> supAdmins = userService.selectUserByRole(Role.SUPERMANAGER);
        List<Integer> supAdminsId = Lists.transform(supAdmins, userToIdFunction);
        User user = userService.currentLogonUser();
        if (supAdminsId.contains(new Integer(user.getId())))
            supAdminsId.remove(new Integer(user.getId()));
        if (user == null) {
            return false;
        }
        if (user.getRole() == Role.SUPERMANAGER && !supAdminsId.contains(user.getId())) {
            return true;
        }
        return false;
    }

    @Override
    public boolean isCheckRequired(ServletRequest req) {
        return true;
    }
}
